#include <iostream>
#include <string>
#include <errno.h>
#include <cstring>
#include <cstdlib>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "Log.hpp"
#include "LockGuard.hpp"
#include"InerAddr.hpp"

using namespace std;

enum
{
    SOCKER_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR,
};

const static int defaultfd = -1;
class UdpServer
{
public:
    UdpServer(uint16_t port) : _sockfd(defaultfd),_port(port),_isrunning(false)
    {
    }
    void InitServer()
    {
        // 1.创建udp socket套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(FATAL, "socket error,%s,%d\n", strerror(errno), errno);
            exit(SOCKER_ERROR);
        }
        LOG(INFO, "socket success,sockfd:%d\n", _sockfd);

        // 2.0 填充sockaddr_in结构
        struct sockaddr_in local;
        bzero(&local, sizeof(local));

        local.sin_family = AF_INET;
        local.sin_port = htons(_port);                  // port 要经过网络传输给对方，通过了网络所以需要网络认识你的序列，so要先把主机（h）序列转网络（n）
        //local.sin_addr.s_addr = inet_addr(_ip.c_str()); //"198.126.2.8"->点分十进制的ip地址转换成4字节的ip地址
        local.sin_addr.s_addr =INADDR_ANY;
        
        // bind绑定
        int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            LOG(FATAL, "bind error,%s,%d", strerror(errno), errno);
            exit(BIND_ERROR);
        }
        LOG(INFO, "socket bind success\n");

    }
    void Start()
    {
        //服务器一般都是死循环
        //UDP是面向数据报的协议，
        _isrunning=true;
        while(true)
        {
            //1.让server先收取数据
            char buffer[1024];
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            ssize_t n=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
            if(n>0)
            {
                buffer[n]=0;
                InetAddr addr(peer);
                LOG(DEBUG,"get a message from [%s:%d]: %s\n",addr.Ip().c_str(),addr.Port(),buffer);
                //2.把server收取的数据，发回给对方
                ssize_t x=sendto(_sockfd,buffer,sizeof(buffer),0,(struct sockaddr*)&peer,len);
            }
            

        }
        _isrunning=false;
    }
    ~UdpServer()
    {
    }

private:
    int _sockfd;
    //string _ip;
    uint16_t _port;
    bool _isrunning;
};